﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

using SimpleFileManager.Manager;

namespace SimpleFileManager
{
    public partial class FileView : UserControl
    {
        private FormMainPresenter _presenter;

        //список доступных comparison
        private List<Comparison<IFilePanelItem>> _comparers = new List<Comparison<IFilePanelItem>>();

        private long _selectedSize = 0;
        private int _selectedFolders = 0;
        private int _selectedFiles = 0;

        private long _totalSize = 0;
        private int _totalFolders = 0;
        private int _totalFiles = 0;

        //строка-шаблон для выделенных файлов и папок
        private string _selectedFilesMask = "{0} k/{1} k in {2}/{3} files, {4}/{5} folders";

        public FormMainPresenter Presenter
        {
            get
            {
                return _presenter;
            }
            set
            {
                if (value != null)
                {
                    _presenter = value;
                    SetDrives();
                }
            }
        }

        public void SetDrives()
        {
            //заполнение combobox c использованием особого итератора
            IFolderIterator drives = _presenter.GetDrives();
            while (!drives.IsDone())
            {
                cmbDrives.Items.Add(drives.CurrentItem.Name);
                drives.Next();
            }
            //cmbDrives.SelectedIndex = 0;
        }

        public IFilePanelItem SelectedItems
        {
            get
            {
                IFilePanelItem selected = new FilePanelItemComposite();
                foreach (ListViewItem item in lvFiles.SelectedItems)
                {
                    //кнопка перхода в род. папку не учитывается
                    if (item.ImageIndex != 3)
                        selected.Add(item.Tag as IFilePanelItem);
                }
                return selected;
            }
        }

        public FileView()
        {
            InitializeComponent();
            _comparers.Add(CompareFilePanelItemsWithName);
            _comparers.Add(CompareFilePanelItemsWithSize);
            _comparers.Add(CompareFilePanelItemsWithTime);
            //загрузка иконок
            try
            {
                lvFiles.SmallImageList = new ImageList();
                lvFiles.SmallImageList.Images.AddRange(new Image[]
                {
                    (Image)Properties.Resources.FileSmall,
                    (Image)Properties.Resources.FolderSmall,
                    (Image)Properties.Resources.DriveSmall,
                    (Image)Properties.Resources.UpSmall
                });
                lvFiles.LargeImageList = new ImageList();
                lvFiles.LargeImageList.Images.AddRange(new Image[]
                {
                    (Image)Properties.Resources.FileLarge,
                    (Image)Properties.Resources.FolderLarge,
                    (Image)Properties.Resources.DriveLarge,
                    (Image)Properties.Resources.UpLarge
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        // получаем и задачем внешний вид lvFiles
        public View View
        {
            get
            {
                return lvFiles.View;
            }
            set
            {
                if (value != System.Windows.Forms.View.Details)
                {
                    HideLines();
                }
                lvFiles.View = value;
            }
        }

        //доcтуп к control из другого потока
        public void InvokeIfRequired(Action action)
        {
            if (InvokeRequired)
            {
                Invoke(action);
            }
            else
            {
                action();
            }
        }

        public void ShowLines()
        {
            for (int i = 0; i < lvFiles.Items.Count; i++)
            {
                if ((i % 2) == 0)
                {
                    InvokeIfRequired(() => lvFiles.Items[i].BackColor = SystemColors.Window);
                }
                else
                {
                    InvokeIfRequired(() => lvFiles.Items[i].BackColor = SystemColors.Control);
                }
            }
        }

        public void HideLines()
        {
            foreach (ListViewItem item in lvFiles.Items)
            {
                item.BackColor = SystemColors.Window;
            }
        }

        //отображение содержимого модели при помощи итератора
        public void ShowFolderContent(IFolderIterator di)
        {
            try
            {
                InvokeIfRequired(() => lvFiles.Items.Clear());
                InvokeIfRequired(() => lvFiles.BeginUpdate());
                ShowParentFolderButton();
                lblCurrentDirectory.Text = di.DirectoryPath;
                while (!di.IsDone())
                {
                    ListViewItem lvi = new ListViewItem()
                    {
                        Text = di.CurrentItem.Name,
                        Tag = di.CurrentItem,
                        ImageIndex = (int)di.CurrentItem.Type
                    };
                    lvi.SubItems.Add(new ListViewItem.ListViewSubItem()
                    {
                        Text = di.CurrentItem.Type == FilePanelItemType.File ?
                            di.CurrentItem.Size.ToString() : "<Folder>"
                    });
                    lvi.SubItems.Add(new ListViewItem.ListViewSubItem()
                    {
                        Text = di.CurrentItem.LastAccessTime.ToString()
                    });
                    InvokeIfRequired(() => lvFiles.Items.Add(lvi));
                    di.Next();
                }
                InvokeIfRequired(() => lblCurrentDirectory.Text = di.DirectoryPath);
                _totalFiles = di.TotalFiles;
                _totalFolders = di.TotalFolders;
                _totalSize = di.TotalSize;
                _selectedFolders = 0;
                _selectedFiles = 0;
                _selectedSize = 0;
                ChangeSelectedFilesStatusString();
                InvokeIfRequired(() => lvFiles.Items[0].Selected = true);
                if (lvFiles.View == System.Windows.Forms.View.Details)
                    ShowLines();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                InvokeIfRequired(() => lvFiles.EndUpdate());
            }
        }

        private void ChangeSelectedFilesStatusString()
        {
            InvokeIfRequired(() => lblSelectedFiles.Text = string.Format(_selectedFilesMask,
                _selectedSize / 1024, _totalSize / 1024, _selectedFiles, _totalFiles, _selectedFolders, _totalFolders));
        }

        private void ShowParentFolderButton()
        {
            ListViewItem lviRoot = new ListViewItem()
            {
                Text = "..",
                Tag = new PseudoFolder(".."),
                ImageIndex = 3
            };
            InvokeIfRequired(() => lvFiles.Items.Add(lviRoot));
        }

        private void lvFiles_ItemActivate(object sender, EventArgs e)
        {
            if (lvFiles.SelectedItems.Count == 1)
            {
                try
                {
                    _presenter.MakeAction(lvFiles.SelectedItems[0].Tag as IFilePanelItem);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Impossible action");
                }
            }
        }

        private void btnParent_Click(object sender, EventArgs e)
        {
            _presenter.GoToParentDirectory();
        }

        private void btnRoot_Click(object sender, EventArgs e)
        {
            _presenter.GoToRootDirectory();
        }

        private void cmbDrives_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (_presenter != null)
                {
                    _presenter.MakeAction(FilePanelItemFactory.CreateDrive(cmbDrives.SelectedItem.ToString()));
                }
                cmbDrives.Tag = cmbDrives.SelectedItem;
            }
            catch (FileManagerException)
            {
                MessageBox.Show("Please choose another drive");
                cmbDrives.SelectedItem = cmbDrives.Tag;
            }
        }

        private void FileView_KeyUp(object sender, KeyEventArgs e)
        {
            //обработка нажатия клавиши backspace
            switch (e.KeyCode)
            {
                case Keys.Back: _presenter.GoToParentDirectory(); break;
            }
        }

        private int CompareFilePanelItemsWithName(IFilePanelItem i1, IFilePanelItem i2)
        {
            return string.Compare(i1.Name, i2.Name);
        }

        private int CompareFilePanelItemsWithSize(IFilePanelItem i1, IFilePanelItem i2)
        {
            return i1.Size == i2.Size ? 0 :
                i1.Size > i2.Size ? 1 : -1;
        }

        private int CompareFilePanelItemsWithTime(IFilePanelItem i1, IFilePanelItem i2)
        {
            return DateTime.Compare(i1.LastAccessTime, i2.LastAccessTime);
        }

        private void lvFiles_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            _presenter.SortPanelItems(_comparers[e.Column]);
        }

        private void lvFiles_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            int k = e.IsSelected ? 1 : -1;
            switch (e.Item.ImageIndex)
            {
                case 0:
                    _selectedFiles += k;
                    _selectedSize += k * long.Parse(e.Item.SubItems[1].Text);
                    break;
                case 1:
                    _selectedFolders += k;
                    break;
            }
            ChangeSelectedFilesStatusString();
        }
    }
}
